
package com.benimetum.managers;

import com.benimetum.database.Sparql;
import com.benimetum.exceptions.DatabaseConnectException;
import com.benimetum.exceptions.DatabaseWriteOrDeleteException;
import com.benimetum.items.*;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.query.ResultSetFormatter;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Ethem Cem Ozkan
 * @email ethemcem.ozkan@gmail.com
 * No 07110604
 */
public class ForumManager
{
    private final static String RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
    private final static String ETU="http://www.benimetum.com/benimetum.owl#";
    
    /**
     * forum oluşturur
     * @param courseId
     * @throws DatabaseWriteOrDeleteException
     * @throws DatabaseConnectException 
     */
    public static void createForum(String courseId) throws DatabaseWriteOrDeleteException, DatabaseConnectException {
	Sparql.insertProperty(ETU+"f"+courseId, RDF+"type", ETU+"Forum");
	Sparql.insertLiteral(ETU+"f"+courseId, ETU+"id", "f"+courseId);
	Sparql.insertProperty(ETU+"f"+courseId, ETU+"regardingTo", ETU+courseId);
	Sparql.insertProperty(ETU+courseId, ETU+"hasForum", ETU+"f"+courseId);
    }
    
    /**
     * başlık oluşturur
     * @param forumId
     * @param userId
     * @param content 
     */
    public static void createTopic(String forumId, String userId, String content ,String header){
	  Random random=new Random();
	  int id=random.nextInt(10000000);
	  String date=""+new Date().getTime();
	  try {
		Sparql.insertProperty(ETU+"t"+id, RDF+"type", ETU+"Topic");
		Sparql.insertProperty(ETU+"t"+id, ETU+"about", ETU+forumId);
		Sparql.insertProperty(ETU+forumId, ETU+"hasTopics", ETU+"t"+id);
		Sparql.insertLiteral(ETU+"t"+id, ETU+"text", content);
		Sparql.insertLiteral(ETU+"t"+id, ETU+"date", date);
		Sparql.insertLiteral(ETU+"t"+id, ETU+"id", "t"+id);
		Sparql.insertLiteral(ETU+"t"+id, ETU+"header", header);
		Sparql.insertProperty(ETU+"t"+id, ETU+"openedBy", ETU+userId);
		Sparql.insertProperty(ETU+userId, ETU+"hasTopic", ETU+"t"+id);
	  } catch (DatabaseConnectException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  } catch (DatabaseWriteOrDeleteException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  }
    }
    
    /**
     * topiğe yazılan cevapları oluşturur
     * @param topicId
     * @param userId
     * @param content 
     */
    public static void createReply(String topicId, String userId, String content, String header){
	  Random random=new Random();
	  int id=random.nextInt(10000000);
	  String date=""+new Date().getTime();
	  try {
		Sparql.insertProperty(ETU+"r"+id, RDF+"type", ETU+"Reply");
		Sparql.insertProperty(ETU+"r"+id, ETU+"createdIn", ETU+topicId);
		Sparql.insertProperty(ETU+topicId, ETU+"hasReplies", ETU+"r"+id);
		Sparql.insertLiteral(ETU+"r"+id, ETU+"text", content);
		Sparql.insertLiteral(ETU+"r"+id, ETU+"id", "r"+id);
		Sparql.insertLiteral(ETU+"r"+id, ETU+"date", date);
		Sparql.insertLiteral(ETU+"r"+id, ETU+"header", header);
		Sparql.insertProperty(ETU+"r"+id, ETU+"openedBy", ETU+userId);
		Sparql.insertProperty(ETU+userId, ETU+"hasReply", ETU+"t"+id);
	  } catch (DatabaseConnectException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  } catch (DatabaseWriteOrDeleteException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  }
    }
    
    /**
     * cevap siler
     * @param replyId 
     */
    public static void deleteReply(String replyId){
	  try {
		String repliesTopicId = getRepliesTopicId(replyId);
		String repliesUserId = getRepliesUserId(replyId);
		Sparql.removeLiteral(ETU+replyId, ETU+"text");
		Sparql.removeLiteral(ETU+replyId, ETU+"id");
		Sparql.removeLiteral(ETU+replyId, ETU+"date");
		Sparql.removeResource(ETU+replyId, ETU+"createdIn", ETU+repliesTopicId);
		Sparql.removeResource(ETU+repliesTopicId, ETU+"hasReplies", ETU+replyId);
		Sparql.removeResource(ETU+replyId, ETU+"openedBy", ETU+repliesUserId);
		Sparql.removeResource(ETU+repliesUserId, ETU+"hasReply", ETU+replyId);
		Sparql.removeResource(ETU+replyId, RDF+"type", ETU+"Reply");
	  } catch (DatabaseWriteOrDeleteException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  } catch (DatabaseConnectException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  }
    }
    
    /**
     * konu siler
     * @param topicId 
     */
    public static void deleteTopic(String topicId){
	  try {
		ArrayList<Reply> topicsReplies = getTopicsReplies(topicId);
		Iterator<Reply> iterator = topicsReplies.iterator();
		while(iterator.hasNext()){
		    Reply next = iterator.next();
		    deleteReply(next.getId());
		}
		String userId=getTopicsUserId(topicId);
		String forumId=getForumId(topicId);
		Sparql.removeLiteral(ETU+topicId, ETU+"text");
		Sparql.removeLiteral(ETU+topicId, ETU+"date");
		Sparql.removeLiteral(ETU+topicId, ETU+"id");
		Sparql.removeResource(ETU+topicId, ETU+"about", ETU+forumId);
		Sparql.removeResource(ETU+forumId, ETU+"hasTopics", ETU+topicId);
		Sparql.removeResource(ETU+topicId, ETU+"openedBy", ETU+userId);
		Sparql.removeResource(ETU+userId, ETU+"hasTopic", ETU+topicId);
		Sparql.removeResource(ETU+topicId, RDF+"type", ETU+"Topic");
	  } catch (DatabaseWriteOrDeleteException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  } catch (DatabaseConnectException ex) {
		Logger.getLogger(ForumManager.class.getName()).log(Level.SEVERE, null, ex);
	  }
    }
    
    /**
     * topiğe yazılmış cevapları döndürür
     * @param TopicId
     * @return 
     */
    public static ArrayList<Reply> getTopicsReplies(String TopicId){
	  String query="select ?id ?userId ?header ?text ?date  where{?topic rdf:type etu:Topic. ?topic etu:id \""+TopicId+"\". ?topic etu:hasReplies ?reply. ?reply etu:openedBy ?user. ?user etu:id ?userId. ?reply etu:id ?id. ?reply etu:header ?header.?reply etu:text ?text. ?reply etu:date ?date}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Reply> array=new ArrayList<Reply>();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
		QuerySolution next = iterator.next();
		String userId = next.get("userId").toString();
		Person user = null;
		if(userId.contains("st"))
		    user=StudentManager.findStudentById(userId);
		else if(userId.contains("t"))
		    user=TeacherManager.getTeacherById(userId);
		array.add(new Reply(next.get("id").toString(), next.get("text").toString(),next.get("header").toString(), TopicId, new Date(Long.parseLong(next.get("date").toString())), user));
	  }
	  return array;
    }
    
    public static Reply[] getTopicsRepliesArray(String TopicId){
	  String query="select ?id ?userId ?header ?text ?date  where{?topic rdf:type etu:Topic. ?topic etu:id \""+TopicId+"\". ?topic etu:hasReplies ?reply. ?reply etu:openedBy ?user. ?user etu:id ?userId. ?reply etu:id ?id. ?reply etu:header ?header.?reply etu:text ?text. ?reply etu:date ?date}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Reply> array=new ArrayList<Reply>();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  while(iterator.hasNext()){
		QuerySolution next = iterator.next();
		String userId = next.get("userId").toString();
		Person user = null;
		if(userId.contains("st"))
		    user=StudentManager.findStudentById(userId);
		else if(userId.contains("t"))
		    user=TeacherManager.getTeacherById(userId);
		array.add(new Reply(next.get("id").toString(), next.get("text").toString(),next.get("header").toString(), TopicId, new Date(Long.parseLong(next.get("date").toString())), user));
	  }
	  Reply[] replies=new Reply[array.size()];
	  return array.toArray(replies);
    }
    
    /**
     * idsi verilen replyyın hangi topiğe ait olduğunu döndürür
     * @param replyId
     * @return 
     */
    public static String getRepliesTopicId(String replyId){
	  String query="select ?id where{?reply rdf:type etu:Reply. ?reply etu:id \""+replyId+"\". ?reply etu:createdIn ?topic. ?topic etu:id ?id}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty())
		return toList.get(0).get("id").toString();
	  return null;
    }
    
    /**
     * cevabın hangi kullanıcıya ait olduğunu bulur
     * @param replyId
     * @return 
     */
    public static String getRepliesUserId(String replyId){
	  String query="select ?id where{?reply rdf:type etu:Reply. ?reply etu:id \""+replyId+"\". ?reply etu:openedBy ?user. ?user etu:id ?id}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty())
		return toList.get(0).get("id").toString();
	  return null;
    }
    
    /**
     * topiğin hangi usera ait olduğunu bulur
     * @param topicId
     * @return 
     */
    public static String getTopicsUserId(String topicId){
	  String query="select ?id where{?topic rdf:type etu:Topic. ?topic etu:id \""+topicId+"\". ?topic etu:openedBy ?user. ?user etu:id ?id}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty())
		return toList.get(0).get("id").toString();
	  return null;
    }
    
    /**
     * topiğin hangi foruma ait olduğunu bulur
     * @param topicId
     * @return 
     */
    public static String getForumId(String topicId){
	  String query="select ?id where{?topic rdf:type etu:Topic. ?topic etu:id \""+topicId+"\". ?topic etu:about ?forum. ?forum etu:id ?id}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty())
		return toList.get(0).get("id").toString();
	  return null;
    }
    
    /**
     * idsi verilen topiği döndürür.
     * @param topicId
     * @return 
     */
    public static Topic getTopic(String topicId){
	  String query="select ?date ?userId ?header ?text ?id ?forumId where{?topic rdf:type etu:Topic. ?topic etu:id \""+topicId+"\". ?topic etu:about ?forum.?topic etu:openedBy ?user.?user etu:id ?userId. ?forum etu:id ?forumId.?topic etu:id ?id. ?topic etu:header ?header.?topic etu:date ?date. ?topic etu:text ?text}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  ArrayList<Reply> topicsReplies = getTopicsReplies(topicId);
	  Reply[] array=new Reply[topicsReplies.size()];
	  array=topicsReplies.toArray(array);
	  String userId=toList.get(0).get("userId").toString();
		Person person=null;
		if(userId.startsWith("st"))
		    person=StudentManager.findStudentById(userId);
		else if(userId.startsWith("t"))
		    person=TeacherManager.getTeacherById(userId);
	  return new Topic(toList.get(0).get("id").toString(), new Date(Long.parseLong(toList.get(0).get("date").toString())), toList.get(0).get("text").toString(),toList.get(0).get("header").toString(), array, toList.get(0).get("forumId").toString(),person);
    }
    
    public static String getCourseForum(String courseId){
	  String query="select ?id where{?course rdf:type etu:Course. ?course etu:id \""+courseId+"\". ?course etu:hasForum ?forum. ?forum etu:id ?id.}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty())
		return toList.get(0).get("id").toString();
	  return null;
    }
    
    public static Topic[] getForumsTopics(String forumId){
	  String query="select ?date ?text ?header ?id ?userId where{?forum rdf:type etu:Forum. ?forum etu:id \""+forumId+"\". ?forum etu:hasTopics ?topic. ?topic etu:openedBy ?user.?user etu:id ?userId.?topic etu:id ?id. ?topic etu:header ?header. ?topic etu:date ?date. ?topic etu:text ?text}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  Iterator<QuerySolution> iterator = toList.iterator();
	  ArrayList<Topic> topics=new ArrayList<Topic>();
	  while (iterator.hasNext()) {
		QuerySolution next = iterator.next();
		ArrayList<Reply> topicsReplies = getTopicsReplies(next.get("id").toString());
		Reply[] array=new Reply[topicsReplies.size()];
		array=topicsReplies.toArray(array);
		String userId=next.get("userId").toString();
		Person person=null;
		if(userId.startsWith("st"))
		    person=StudentManager.findStudentById(userId);
		else if(userId.startsWith("t"))
		    person=TeacherManager.getTeacherById(userId);
		topics.add(new Topic(next.get("id").toString(), new Date(Long.parseLong(next.get("date").toString())), next.get("text").toString(),next.get("header").toString(), array, forumId,person));
	  }
	  Topic[] array=new Topic[topics.size()];
	  return topics.toArray(array);
    }
    
    public static Forum getForum(String forumId){
	  String query="select ?courseId where{?forum rdf:type etu:Forum. ?forum etu:id \""+forumId+"\". ?forum etu:regardingTo ?course. ?course etu:id ?courseId.}";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty()){
		return new Forum(getForumsTopics(forumId), CourseManager.getCourse(toList.get(0).get("courseId").toString()));
	  }
	  return null;
    }
    
    public static Forum getCoursesForum(String courseId){
	  String query="select ?id ?courseId where{?course rdf:type etu:Course. ?course etu:id \""+courseId+"\".?course etu:hasForum ?forum.?forum etu:id ?id }";
	  ResultSet search = Sparql.search(query);
	  List<QuerySolution> toList = ResultSetFormatter.toList(search);
          Sparql.close();
	  if(!toList.isEmpty()){
		return new Forum(getForumsTopics(toList.get(0).get("id").toString()), CourseManager.getCourse(courseId));
	  }
	  return null;
    }
    
    public static Forum[] getStudentForums(String studentId){
	  Course[] studentsCourse = CourseManager.getStudentsCourse(studentId);
	  Forum[] forums=new Forum[studentsCourse.length];
	  for (int i = 0; i < studentsCourse.length; i++) {
		forums[i]=ForumManager.getCoursesForum(studentsCourse[i].getID());
	  }
	  return forums;
    }
    
    public static Forum[] getTeacherForums(String teacherId){
	  Course[] teachersCourses = TeacherManager.getTeachersCourses(teacherId);
	  Forum[] forums=new Forum[teachersCourses.length];
	  for (int i = 0; i < teachersCourses.length; i++) {
		forums[i]=ForumManager.getCoursesForum(teachersCourses[i].getID());
	  }
	  return forums;
    }
}
